﻿@using System.IO;
@using System.Text.Json;

<h5>@title</h5>

<div>
    <Table @ref="@LogTable" TItem="C485LogItem" Items="@LogTableData?.Take(LogTableData.Count)"
           IsStriped="true" IsBordered="true" AllowResizing="true" IsFixedHeader="true" Height="240"
           ClickToSelect="true" >
        <TableColumns>
            <TableColumn @bind-Field="@context.time" Text="时间" Align="Alignment.Left" Width="120" Readonly="true" />
            <TableColumn @bind-Field="@context.cmd_type" Text="指令类型" Align="Alignment.Center" Width="140" Readonly="true" />
            <TableColumn @bind-Field="@context.cmd" Text="指令码" Align="Alignment.Center" Width="80" Readonly="true" />
            <TableColumn @bind-Field="@context.des" Text="指令描述" Align="Alignment.Center" Width="180" Readonly="true" />
            <TableColumn @bind-Field="@context.data" Text="数据" Align="Alignment.Left" Readonly="true" />
        </TableColumns>
    </Table>
</div>

@code {
    private string title = "485 通讯记录";
    public class C485LogItem
    {
        public string time { get; set; } = "";      // HH:mm:ss:xxx
        public string data { get; set; } = "";      // 例如 DD 00 09 01 02 03 01 01 01 00 01 50 59 88
        public string cmd_type { get; set; } = "";  // 指令类型，控制器发送，控制器应答，智能模块发送，智能模块应答
        public int len { get; set; } = 0;           // 数据长度
        public string cmd { get; set; } = "";       // 解析的指令，例如0x0204
        public string des { get; set; } = "";       // 指令描述，库设定温度取得
    }
    public Table<C485LogItem>? LogTable { get; set; } // table 控件
    public List<C485LogItem>? LogTableData { get; set; } = new();

    protected override void OnInitialized()
    {
        base.OnInitialized();
    }

    // 增加数据, dir表示方向，1 = 发送，0 = 接收
    public void AddItem(byte[] data, int len, int dir)
    {
        if (len == 0) return;

        C485LogItem log = new();
        log.time = System.DateTime.Now.ToString("HH:mm:ss:fff");
        // byte[]转换为16进制字符串, 截取最大64个
        if(len <= 64)
            log.data = BitConverter.ToString(data[..len]).Replace("-", " ");
        else
            log.data = BitConverter.ToString(data[..64]).Replace("-", " ") + "...";

        if (len < 14) // 收到数据异常
        {
            log.des = "数据不全, 等待更多数据";
            LogTableData.Insert(0, log);
            InvokeAsync(StateHasChanged);
            return;
        }

        if(data[0] != 0xDD || data[len - 1] != 0x88)
        {
            log.des = "数据格式错误：头尾标志";
        }
        log.len = (int)data[1] << 8 | data[2];
        int cmd = ((int)data[4] << 8 | data[5]);
        log.cmd = string.Format("0x{0:X4}", cmd);
        if (dir == 1)
            log.cmd_type = (log.cmd == "0x0102" || log.cmd == "0x0103") ? "←发:智能模块-应答" : "←发:智能模块-指令";
        else
            log.cmd_type = (log.cmd == "0x0102" || log.cmd == "0x0103") ? "→收:控制器-应答" : "→收:控制器-指令";

        int value_type = (int)data[8];
        int value_len = (int)data[9] << 8 | data[10];
        log.des = C485GetDesByCmd(cmd);

        LogTableData.Insert(0, log);
        InvokeAsync(StateHasChanged);
    }

    private string C485GetDesByCmd(int cmd)
    {
        switch (cmd >> 8)
        {     // 根据cmd的高位分块检索, 加快检索速度
            case 0x01:
                switch ((byte)cmd)
                {
                    case 0x01:
                        return "通信监测";
                    case 0x02:
                        return "无效指令应答";
                    case 0x03:
                        return "自动发送指令应答";
                    case 0x11:
                        return "设备重启";
                    case 0x12:
                        return "程序升级开始";
                    case 0x13:
                        return "程序升级传送";
                    case 0x14:
                        return "程序版本取得";
                    case 0x15:
                        return "硬件版本取得";
                    case 0x16:
                        return "厂家代码取得";

                    case 0x21:
                        return "设备类型取得";
                    case 0x22:
                        return "设备功能取得";
                    case 0x23:
                        return "系统时间设定";
                    case 0x24:
                        return "系统时间取得";
                    case 0x25:
                        return "运行状态取得";
                    case 0x26:
                        return "现在故障解除";
                    case 0x27:
                        return "现在故障状态取得";
                    case 0x28:
                        return "压缩机实时状态取得";
                    case 0x29:
                        return "门状态取得";
                    case 0x2A:
                        return "灯状态取得";
                    case 0x2B:
                        return "功率值取得";
                    case 0x2C:
                        return "电池电压值取得";
                    case 0x2D:
                        return "联网状态取得";
                    case 0x2E:
                        return "冰柜蒸发风机状态设定";
                    case 0x2F:
                        return "冰柜蒸发风机状态取得";
                    case 0x30:
                        return "灯状态设定";
                    case 0x31:
                        return "灯电流取得";
                    case 0x32:
                        return "4G 信号值取得";
                    default:
                        return "无效指令"; // cmd not support
                }
            case 0x02:                          // 基本数据相关
                switch ((byte)cmd)
                {
                    case 0x01:
                        return "库制冷/制热模式设定";
                    case 0x02:
                        return "库制冷/制热模式取得";
                    case 0x03:
                        return "库设置温度设定";
                    case 0x04:
                        return "库设置温度取得";
                    case 0x05:
                        return "库高温报警温度设定";
                    case 0x06:
                        return "库高温报警温度取得";
                    case 0x07:
                        return "库低温报警温度设定";
                    case 0x08:
                        return "库低报警温度取得";
                    case 0x09:
                        return "库当前温度取得(显示温度)";
                    case 0x0A:
                        return "库设置温度下限设定";
                    case 0x0B:
                        return "库设置温度下限取得";
                    case 0x0C:
                        return "库设置温度上限设定";
                    case 0x0D:
                        return "库设置温度上限取得";
                    case 0x0E:
                        return "库温度上回差取得";
                    case 0x0F:
                        return "库温度下回差取得";
                    case 0x10:
                        return "库传感器故障压缩机开机时间取得";
                    case 0x11:
                        return "库传感器故障压缩机关机时间取得";
                    case 0x12:
                        return "库温度补偿值设定";
                    case 0x13:
                        return "库温度补偿值取得";
                    case 0x14:
                        return "库除霜周期/压缩机保护周期取得";
                    case 0x15:
                        return "库除霜时间/压缩机保护时间取得";
                    case 0x16:
                        return "库压缩机最小停机时间取得";
                    case 0x17:
                        return "库环境温度取得";
                    case 0x18:
                        return "库实际温度（温度传感器测量温度）取得";
                    case 0x19:
                        return "库本地控制状态取得";
                    default:
                        return "无效指令"; // cmd not support
                }
            case 0x05:                          // 统计数据相关
                switch ((byte)cmd)
                {
                    case 0x01:
                        return "开门次数清空";
                    case 0x02:
                        return "开门次数取得";
                    case 0x03:
                        return "客流次数清空";
                    case 0x04:
                        return "客流次数取得";
                    default:
                        return "无效指令"; // cmd not support
                }
            case 0x06:                          // 节能照明相关, 本APP不支持
            default:
                return "无效指令"; // cmd not support
        }

    }

    // 自身改变数据, 记录
    // private Task<bool> OnSaveAsync(C485LogItem item, ItemChangedType changedType)
    // {
    //     return Task.FromResult(true);
    // }

}